/**

   @mainpage Workload Generator Documentation
   
   @section intro Introduction
   
   Workload Generator is an application that reads in a workload signature expressed as an array of JSON objects that each describe a workload for a resource and reproduces that signature on the machine.
   
   @section build Building
   
   In the project directory, run make and a binary file will be compiled into the "bin" directory.

   @section configuration Configuring
   
   The generator uses a config file inside the "conf" directory called "config.json". In JSON, it consists of an array of objects that describe the workload for each resource.
   
   All objects have the following attributes:
   
   Name
   
   A name identifying the resource the object describes. Acceptable values are:
   
   cpu disk memory l1_cache l2_cache
   
   Distribution
   
   A distribution which describes the interarrival time between two jobs using this resource in milliseconds.  Probability distributions are represented as JSON objects with the following structure.
   
   @code
   {"type":"constant", "value":##}        Constant
   {"type":"uniform", "min":##, "max":##} Uniform
   {"type":"exponential", "lambda":##}    Exponential
   {"type":"normal", "mean":##, "std":##} Normal
   @endcode

   Modes

   Describe what the generator will do and how likely a given job is to perform each mode.
   
   All modes have a "name" attribute.
   
   All modes have a "p" attribute where 0 <= p <= 1.
   
   The sum of all the modes' probabilities must sum to 1, otherwise the generator will fail.

   All modes have extra attributes. If an attribute specifies a time period, the units are in milliseconds. If it specifies some space (i.e. space to read from disk) then the units are in kilobytes (1000 bytes).
   
   The exception is the l1_cache and l2_cache resources which treat all arguments concerning space as bytes.

   Some resources have exra attributes, these are described as follows by resource:

   cpu: N/A

   disk: filesize (kB = 1000 bytes)

   The amount of space to use for the disk workload. A file identified by the disk resource's thread id is written to the ./tmp/ directory where the read and write operations will occur.

   memory: memory_size (kb = 1000 bytes)

   The amount of memory to allocate for the memory workload. One chunk of this size is allocated for all read and write operations.

   l\#_cache: cache_size (bytes)

   The size of the cache. One chunk of this size, minus 100 bytes to account for error, is allocated for all read write operations.

   @section running Running

   To run the generator, run the "generator" file from inside the "./bin" directory.
   
*/

/**
    @file main.c
    @brief Main file for the Workload Generator
 */

#include <pthread.h>
#include "generator.h"
#include "cpu.h"
#include "disk.h"
#include "memory.h"
#include "cache.h"

/**
    The generator's main flow of execution.

    Sets up the workload generator and runs the generator for each resource. */
int main() {
  setup_generator();
  cJSON *json = parse_config();
  pthread_t threads[5];
  workload_generator(json, "cpu", setup_cpu, &threads[0]);
  workload_generator(json, "disk", setup_disk, &threads[1]);
  workload_generator(json, "memory", setup_memory, &threads[2]);
  workload_generator(json, "l1_cache", setup_l1_cache, &threads[3]);
  workload_generator(json, "l2_cache", setup_l2_cache, &threads[4]);
  int i = 0;
  for(i; i < 5; i++) {
    pthread_join(threads[i], NULL); /* Wait for all resource threads to finish */
  }
}
